#三种回归算法
import time
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import SVR  # 新增支持向量机回归
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.preprocessing import StandardScaler  # 用于SVR特征缩放

# 加载数据
data = pd.read_csv('StudentPerformanceFactors.csv')
print(f"原始数据量: {len(data)} 条")

# 删除空值
data = data.dropna()
print(f"去除空值后的数据量: {len(data)} 条")

# 二值编码
binary_cols = {
    'Extracurricular_Activities': {'No': 0, 'Yes': 1},
    'Internet_Access': {'No': 0, 'Yes': 1},
    'Learning_Disabilities': {'No': 0, 'Yes': 1}
}
for col, mapping in binary_cols.items():
    data[col] = data[col].map(mapping)

# 多类别编码
multi_cols = {
    'Parental_Involvement': {'Low': 0, 'Medium': 1, 'High': 2},
    'Access_to_Resources': {'Low': 0, 'Medium': 1, 'High': 2},
    'Motivation_Level': {'Low': 0, 'Medium': 1, 'High': 2},
    'Family_Income': {'Low': 0, 'Medium': 1, 'High': 2},
    'Teacher_Quality': {'Low': 0, 'Medium': 1, 'High': 2},
    'School_Type': {'Public': 0, 'Private': 1},
    'Peer_Influence': {'Negative': 0, 'Neutral': 1, 'Positive': 2},
    'Parental_Education_Level': {'High School': 0, 'College': 1, 'Postgraduate': 2},
    'Distance_from_Home': {'Near': 0, 'Moderate': 1, 'Far': 2},
    'Gender': {'Male': 0, 'Female': 1}
}
for col, mapping in multi_cols.items():
    data[col] = data[col].map(mapping)

# 特征 & 标签
X = data.drop(columns=['Exam_Score'])
y = data['Exam_Score']

# 数据划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 特征标准化（仅用于SVR）
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 模型列表
models = {
    'Linear Regression': LinearRegression(),
    'Random Forest': RandomForestRegressor(n_estimators=100, random_state=42),
    'Support Vector Regression': SVR(kernel='rbf', C=1.0, epsilon=0.1)  # 核函数选择RBF
}

# 存储结果
results = []

# 遍历模型并评估
for name, model in models.items():
    start_time = time.time()
    
    # 区分是否需标准化数据
    if name == 'Support Vector Regression':
        model.fit(X_train_scaled, y_train)
        y_pred = model.predict(X_test_scaled)
    else:
        model.fit(X_train, y_train)
        y_pred = model.predict(X_test)
    
    # 计算指标
    mse = mean_squared_error(y_test, y_pred)
    mae = mean_absolute_error(y_test, y_pred)
    r2 = r2_score(y_test, y_pred)
    elapsed_time = time.time() - start_time

    results.append({
        'Model': name,
        'MSE': mse,
        'MAE': mae,
        'R2 Score': r2,
        'Time (s)': round(elapsed_time, 3)
    })

    # 可视化预测效果
    plt.figure(figsize=(6, 5))
    sns.scatterplot(x=y_test, y=y_pred)
    plt.plot([y.min(), y.max()], [y.min(), y.max()], 'r--')
    plt.title(f'{name} - Predicted vs Actual')
    plt.xlabel('Actual Exam Score')
    plt.ylabel('Predicted Exam Score')
    plt.grid(True)
    plt.tight_layout()
    plt.show()

# 转为DataFrame并展示对比
results_df = pd.DataFrame(results)
print("\n模型性能比较：")
print(results_df.to_markdown(index=False))